#include "Cache/LRUCache.hh"
#include "nlohmann/json.hpp"
#include "Log/Log.hh"
#include <fstream>



using std::ifstream;
using std::ofstream;

LRUCache::LRUCache(size_t capacity)
    : _capacity(capacity){

}

LRUCache::LRUCache(const LRUCache& rhs)
    : _capacity(rhs._capacity)
    , _cache(rhs._cache)
    , _resultList(rhs._resultList){

}

void LRUCache::addElement(const string& key, const string& json){

    if(_resultList.size() == _capacity){
        auto del = _resultList.back();
        _resultList.pop_back();
        _cache.erase(del.first);
    }

    // 如果找到了这个 key
    if(_cache.find(key) != _cache.end()){
        _resultList.splice(_resultList.begin(), _resultList, _cache[key]);
        return;
    }

    _resultList.push_front({key, json});
    _cache[key] = _resultList.begin();


}

void LRUCache::addElement(LRUCache& rhs){

    const auto& list = rhs.getResultList();
    for(auto& elem : list){
        addElement(elem.first, elem.second);
    }
}


void LRUCache::readFromFile(const string &filename){
    nlohmann::json j;
    ifstream ifs(filename);
    ifs >> j;
    if(j.is_null() == false){return;}
    
    for(auto it = j.begin(); it != j.end(); it++){
        for(auto it2 = it->begin(); it2 != it->end(); ){
            addElement(string(*it2++), string(*it2++));
        }
    }
}

void LRUCache::writeToFile(const string &filename){
    ofstream ofs(filename);
    nlohmann::json j(_resultList);
    ofs << j.dump();
}



bool LRUCache::find(const string& key, string& json){
    if(_cache.find(key) == _cache.end()){
        return false;
    }else{
        json = _cache[key]->second;
        _resultList.splice(_resultList.begin(), _resultList, _cache[key]);
        return true;
    }
}

void swapCache(LRUCache& lhs, LRUCache& rhs){
    lhs._cache.swap(rhs._cache);
    lhs._resultList.swap(rhs._resultList);
}


const list<pair<string, string>>& LRUCache::getResultList(){
    return _resultList;
}